/**
 * 插入html字符串插件
 * @file
 * @since 1.2.6.1
 */

/**
 * 插入html代码
 * @command inserthtml
 * @method execCommand
 * @param { String } cmd 命令字符串
 * @param { String } html 插入的html字符串
 * @remaind 插入的标签内容是在当前的选区位置上插入，如果当前是闭合状态，那直接插入内容， 如果当前是选中状态，将先清除当前选中内容后，再做插入
 * @warning 注意:该命令会对当前选区的位置，对插入的内容进行过滤转换处理。 过滤的规则遵循html语意化的原则。
 * @example
 * ```javascript
 * //xxx[BB]xxx 当前选区为非闭合选区，选中BB这两个文本
 * //执行命令，插入<b>CC</b>
 * //插入后的效果 xxx<b>CC</b>xxx
 * //<p>xx|xxx</p> 当前选区为闭合状态
 * //插入<p>CC</p>
 * //结果 <p>xx</p><p>CC</p><p>xxx</p>
 * //<p>xxxx</p>|</p>xxx</p> 当前选区在两个p标签之间
 * //插入 xxxx
 * //结果 <p>xxxx</p><p>xxxx</p></p>xxx</p>
 * ```
 */

UE.commands["inserthtml"] = {
    execCommand: function (command, html, notNeedFilter) {
        var me = this,
            range,
            div;
        if (!html) {
            return;
        }
        if (me.fireEvent("beforeinserthtml", html) === true) {
            return;
        }
        range = me.selection.getRange();
        div = range.document.createElement("div");
        div.style.display = "inline";

        if (!notNeedFilter) {
            var root = UE.htmlparser(html);
            //如果给了过滤规则就先进行过滤
            if (me.options.filterRules) {
                UE.filterNode(root, me.options.filterRules);
            }
            //执行默认的处理
            me.filterInputRule(root);
            html = root.toHtml();
        }
        div.innerHTML = utils.trim(html);

        if (!range.collapsed) {
            var tmpNode = range.startContainer;
            if (domUtils.isFillChar(tmpNode)) {
                range.setStartBefore(tmpNode);
            }
            tmpNode = range.endContainer;
            if (domUtils.isFillChar(tmpNode)) {
                range.setEndAfter(tmpNode);
            }
            range.txtToElmBoundary();
            //结束边界可能放到了br的前边，要把br包含进来
            // x[xxx]<br/>
            if (range.endContainer && range.endContainer.nodeType == 1) {
                tmpNode = range.endContainer.childNodes[range.endOffset];
                if (tmpNode && domUtils.isBr(tmpNode)) {
                    range.setEndAfter(tmpNode);
                }
            }
            if (range.startOffset == 0) {
                tmpNode = range.startContainer;
                if (domUtils.isBoundaryNode(tmpNode, "firstChild")) {
                    tmpNode = range.endContainer;
                    if (
                        range.endOffset ==
                        (tmpNode.nodeType == 3
                            ? tmpNode.nodeValue.length
                            : tmpNode.childNodes.length) &&
                        domUtils.isBoundaryNode(tmpNode, "lastChild")
                    ) {
                        me.body.innerHTML = "<p>" + (browser.ie ? "" : "<br/>") + "</p>";
                        range.setStart(me.body.firstChild, 0).collapse(true);
                    }
                }
            }
            !range.collapsed && range.deleteContents();
            if (range.startContainer.nodeType == 1) {
                var child = range.startContainer.childNodes[range.startOffset],
                    pre;
                if (
                    child &&
                    domUtils.isBlockElm(child) &&
                    (pre = child.previousSibling) &&
                    domUtils.isBlockElm(pre)
                ) {
                    range.setEnd(pre, pre.childNodes.length).collapse();
                    while (child.firstChild) {
                        pre.appendChild(child.firstChild);
                    }
                    domUtils.remove(child);
                }
            }
        }

        var child,
            parent,
            pre,
            tmp,
            hadBreak = 0,
            nextNode;
        //如果当前位置选中了fillchar要干掉，要不会产生空行
        if (range.inFillChar()) {
            child = range.startContainer;
            if (domUtils.isFillChar(child)) {
                range.setStartBefore(child).collapse(true);
                domUtils.remove(child);
            } else if (domUtils.isFillChar(child, true)) {
                child.nodeValue = child.nodeValue.replace(fillCharReg, "");
                range.startOffset--;
                range.collapsed && range.collapse(true);
            }
        }
        //列表单独处理
        var li = domUtils.findParentByTagName(range.startContainer, "li", true);
        if (li) {
            var next, last;
            while ((child = div.firstChild)) {
                //针对hr单独处理一下先
                while (
                    child &&
                    (child.nodeType == 3 ||
                        !domUtils.isBlockElm(child) ||
                        child.tagName == "HR")
                    ) {
                    next = child.nextSibling;
                    range.insertNode(child).collapse();
                    last = child;
                    child = next;
                }
                if (child) {
                    if (/^(ol|ul)$/i.test(child.tagName)) {
                        while (child.firstChild) {
                            last = child.firstChild;
                            domUtils.insertAfter(li, child.firstChild);
                            li = li.nextSibling;
                        }
                        domUtils.remove(child);
                    } else {
                        var tmpLi;
                        next = child.nextSibling;
                        tmpLi = me.document.createElement("li");
                        domUtils.insertAfter(li, tmpLi);
                        tmpLi.appendChild(child);
                        last = child;
                        child = next;
                        li = tmpLi;
                    }
                }
            }
            li = domUtils.findParentByTagName(range.startContainer, "li", true);
            if (domUtils.isEmptyBlock(li)) {
                domUtils.remove(li);
            }
            if (last) {
                range.setStartAfter(last).collapse(true).select(true);
            }
        } else {
            while ((child = div.firstChild)) {
                if (hadBreak) {
                    var p = me.document.createElement("p");
                    while (child && (child.nodeType == 3 || !dtd.$block[child.tagName])) {
                        nextNode = child.nextSibling;
                        p.appendChild(child);
                        child = nextNode;
                    }
                    if (p.firstChild) {
                        child = p;
                    }
                }
                range.insertNode(child);
                nextNode = child.nextSibling;
                if (
                    !hadBreak &&
                    child.nodeType == domUtils.NODE_ELEMENT &&
                    domUtils.isBlockElm(child)
                ) {
                    parent = domUtils.findParent(child, function (node) {
                        return domUtils.isBlockElm(node);
                    });
                    if (
                        parent &&
                        parent.tagName.toLowerCase() != "body" &&
                        !(
                            dtd[parent.tagName][child.nodeName] && child.parentNode === parent
                        )
                    ) {
                        if (!dtd[parent.tagName][child.nodeName]) {
                            pre = parent;
                        } else {
                            tmp = child.parentNode;
                            while (tmp !== parent) {
                                pre = tmp;
                                tmp = tmp.parentNode;
                            }
                        }

                        domUtils.breakParent(child, pre || tmp);
                        //去掉break后前一个多余的节点  <p>|<[p> ==> <p></p><div></div><p>|</p>
                        var pre = child.previousSibling;
                        domUtils.trimWhiteTextNode(pre);
                        if (!pre.childNodes.length) {
                            domUtils.remove(pre);
                        }
                        //trace:2012,在非ie的情况，切开后剩下的节点有可能不能点入光标添加br占位

                        if (
                            !browser.ie &&
                            (next = child.nextSibling) &&
                            domUtils.isBlockElm(next) &&
                            next.lastChild &&
                            !domUtils.isBr(next.lastChild)
                        ) {
                            next.appendChild(me.document.createElement("br"));
                        }
                        hadBreak = 1;
                    }
                }
                var next = child.nextSibling;
                if (!div.firstChild && next && domUtils.isBlockElm(next)) {
                    range.setStart(next, 0).collapse(true);
                    break;
                }
                range.setEndAfter(child).collapse();
            }

            child = range.startContainer;

            if (nextNode && domUtils.isBr(nextNode)) {
                domUtils.remove(nextNode);
            }
            //用chrome可能有空白展位符
            if (domUtils.isBlockElm(child) && domUtils.isEmptyNode(child)) {
                if ((nextNode = child.nextSibling)) {
                    domUtils.remove(child);
                    if (nextNode.nodeType == 1 && dtd.$block[nextNode.tagName]) {
                        range.setStart(nextNode, 0).collapse(true).shrinkBoundary();
                    }
                } else {
                    try {
                        child.innerHTML = browser.ie ? domUtils.fillChar : "<br/>";
                    } catch (e) {
                        range.setStartBefore(child);
                        domUtils.remove(child);
                    }
                }
            }
            //加上true因为在删除表情等时会删两次，第一次是删的fillData
            try {
                range.select(true);
            } catch (e) {
            }
        }

        setTimeout(function () {
            range = me.selection.getRange();
            range.scrollToView(
                me.autoHeightEnabled,
                me.autoHeightEnabled ? domUtils.getXY(me.iframe).y : 0
            );
            me.fireEvent("afterinserthtml", html);
        }, 200);
    }
};
